package com.zkingsoft.wechat.pay;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xml.sax.SAXException;

import com.matrix.async.service.AsyncTaskService;
import com.matrix.core.pojo.AjaxResult;
import com.matrix.core.tools.LogUtil;
import com.matrix.core.web.BaseAction;
import com.zkingsoft.bean.BizOrder;
import com.zkingsoft.bean.BizPayLog;
import com.zkingsoft.common.constance.AppConstance;
import com.zkingsoft.common.constance.AsyncTaskType;
import com.zkingsoft.dao.BizCollageInfoDao;
import com.zkingsoft.dao.BizIncomeLogDao;
import com.zkingsoft.dao.BizMyCouponDao;
import com.zkingsoft.dao.BizUserDao;
import com.zkingsoft.externalInterface.common.Signature;
import com.zkingsoft.externalInterface.common.Util;
import com.zkingsoft.externalInterface.protocol.queryProtocol.NotifyData;
import com.zkingsoft.externalInterface.weixinUtil.WeixinServiceUtil;
import com.zkingsoft.redis.RedisUserLoginUtils;
import com.zkingsoft.service.BizActivitiesService;
import com.zkingsoft.service.BizCollageDetailService;
import com.zkingsoft.service.BizCollageInfoService;
import com.zkingsoft.service.BizMyCouponService;
import com.zkingsoft.service.BizOrderService;
import com.zkingsoft.service.BizPayLogService;

/**
 * @description (支付表)
 * @author 何明
 * @date 2018-05-23 00:08
 */
@Controller
@RequestMapping(value = "wxCommon")
public class WxCommonAction extends BaseAction {

	/**
	 * 错误报文占位符
	 */
	private static final String ERRORMSG = "ERRORMSG";
	/**
	 * 异步任务和订单类型的映射关系
	 */
	private static Map<Integer, String> TASK_ORDER_MAPPING = new HashMap<>();
	static {
		// 拼团活动的异步处理任务
		TASK_ORDER_MAPPING.put(AppConstance.ACTIVITIES_COLLAGE, AsyncTaskType.UPDATE_COLLAGE_PAY_TASK);
		TASK_ORDER_MAPPING.put(AppConstance.ORDER_TYPE_VIP, AsyncTaskType.HANDLE_VIP_ORDER);
	}

	@Autowired
	private WeixinServiceUtil weixinServiceUtil;
	@Autowired
	private BizCollageDetailService bizCollageDetailService;
	@Autowired
	RedisUserLoginUtils redisUserLoginUtils;
	@Autowired
	private BizMyCouponService bizMyCouponService;
	@Autowired
	private BizActivitiesService activitiesService;
	@Autowired
	private BizOrderService bizOrderService;
	@Autowired
	private BizCollageInfoService bizCollageInfoService;
	@Autowired
	private BizCollageInfoDao bizCollageInfoDao;
	@Autowired
	private BizUserDao bizUserDao;
	@Autowired
	private BizIncomeLogDao bizIncomeLogDao;
	@Autowired
	private BizMyCouponDao bizMyCouponDao;
	@Autowired
	AsyncTaskService asyncTaskService;
	@Autowired
	BizPayLogService payLogService;

	/**
	 * 微信支付回调接口
	 * 
	 * @param response
	 * @param request
	 * @throws IOException
	 * @throws Exception
	 */
	@Transactional
	@RequestMapping(value = "/wxpayCallback")
	public void payCallBack(HttpServletResponse response, HttpServletRequest request) throws IOException {
		LogUtil.info("微信支付回调start....");

		// 获取输入参数
		String inputLine;
		StringBuffer notityXml = new StringBuffer();
		String resXml = "";
		String orderId = "";
		
		/** 用于测试等待唤醒效果
		try {
			Thread.sleep(1000*5);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		**/
		
		AjaxResult threadResult = new AjaxResult(AjaxResult.STATUS_SUCCESS, "");
		try {
			while ((inputLine = request.getReader().readLine()) != null) {
				notityXml.append(inputLine);
			}
			request.getReader().close();
			NotifyData data = (NotifyData) Util.getObjectFromXML(notityXml.toString(), NotifyData.class);// XMl转对象
			LogUtil.info("notityXml ---- :{} ", notityXml);
			LogUtil.info("----return_code = {}", data.getReturn_code());

			// 返回状态码 SUCCESS/FAIL
			if ("SUCCESS".equals(data.getReturn_code())) {
				// 校验签名
				if (Signature.checkIsSignValidFromResponseString(notityXml.toString())) {
					// 校验业务结果
					if (AppConstance.CODE_SUCCESS.equals(data.getResult_code())) {// 交易是否成功
						// 返回SUCCESS报文
						resXml = AppConstance.RESULT_XML_SUCCESS;

						Double total_fee = Double.parseDouble(data.getTotal_fee());// 支付费用
						String payNum = data.getOut_trade_no();// 商户订单号
						orderId = data.getAttach();
						LogUtil.info("支付回调关键信息---total_fee:{},payNum:{},orderId:{}", total_fee, payNum, orderId);
						// 订单ID
						BigDecimal payMoney = new BigDecimal(total_fee).divide(new BigDecimal(100), 2,
								RoundingMode.HALF_UP);

						// 检验订单状态
						BizOrder order = bizOrderService.findById(orderId);
						if (order != null && AppConstance.PAY_STATUS_DZF == order.getPayStatus()) {
							BizPayLog payLog=new BizPayLog();
							// 校验支付金额
							LogUtil.debug("检查支付金额payMoney={},order.getPayMoney()={}", payMoney, order.getPayMoney());
							/*if (payMoney.equals(order.getPayMoney())) {*/
								
								order.setPayStatus(AppConstance.PAY_STATUS_SUC);
								bizOrderService.modifyByModel(order);
								
								// 根据订单类型创建不同的处理任务
								Map<String, String> dataMap = new HashMap<String, String>();
								dataMap.put("orderId", orderId);
								dataMap.put("payMoney", payMoney.toString());
								dataMap.put("resultCode", data.getResult_code());
								dataMap.put("orderNo", payNum);
								asyncTaskService.createTask(null, getAsyncTaskByOrderType(order.getOrderType()),
										dataMap);
								threadResult.putInMap("status", "success");
								resXml = AppConstance.RESULT_XML_SUCCESS;
								
								recordPayLog(orderId, payMoney, order, payLog, "支付成功",AppConstance.ORDER_PAY_STATUS_SUCCESS);
						/*	} else {
								// 支付金额不对
								String errMsg=String.format("支付金额不对需要支付%s元，实际支付%s元", order.getPayMoney(), payMoney);
								threadResult.putInMap("status", "err");
								threadResult.putInMap("msg",errMsg
										);
								LogUtil.info("支付金额不对");
								recordPayLog(orderId, payMoney, order, payLog, errMsg,AppConstance.ORDER_PAY_STATUS_FAIL);
							}*/
							//记录支付信息
							
						}else{
							LogUtil.info("订单状态不为待付款，order status=", order.getOrderStatus());
						}
						
					} else {
						LogUtil.info("微信标识业务是失败");
						threadResult.putInMap("status", "err");
						threadResult.putInMap("msg", "查询支付信息失败，请联系客服或者刷新支付信息（错误码:001）");
						resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "微信标识业务是失败");
					}
				} else {
					LogUtil.info("无效签名");
					threadResult.putInMap("status", "err");
					threadResult.putInMap("msg", "查询支付信息失败，请联系客服或者刷新支付信息（错误码:002）");
					resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "微信标识业务是失败");
				}
			} else {
				LogUtil.info("通信标识失败");
				threadResult.putInMap("status", "err");
				threadResult.putInMap("msg", "查询支付信息失败，请联系客服或者刷新支付信息（错误码:003）");
				resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "通信标识失败");
			}
		} catch (ParserConfigurationException | IOException | SAXException e) {
			LogUtil.error("支付回调签名错误", e);
			threadResult.putInMap("status", "err");
			threadResult.putInMap("msg", "查询支付信息失败，请联系客服或者刷新支付信息（错误码:004）");
			resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "支付回调签名错误");
		} finally {
			// 通知线程消息
			PayThreadPool.notifyThread(orderId, threadResult);
			sendResultBack(response, resXml);
		}
		return;

	}

	private void recordPayLog(String orderId, BigDecimal payMoney, BizOrder order, BizPayLog payLog, String payRemark,int payStatus) {
		payLog.setJoinId(orderId);
		payLog.setPayMoney(payMoney);
		payLog.setPayOrderNum(order.getOrderNo());
		payLog.setPayRemark(payRemark);
		payLog.setPayStatus(payStatus);
		payLog.setCreateBy(AppConstance.SYSTEM_USER);
		payLog.setUpdateBy(AppConstance.SYSTEM_USER);
		payLogService.add(payLog);
	}

	private String getAsyncTaskByOrderType(Integer orderType) {
		return TASK_ORDER_MAPPING.get(orderType);
	}

	private void sendResultBack(HttpServletResponse response, String resXml) throws IOException {
		LogUtil.info("返回微信数据={}", resXml);
		ServletOutputStream out = response.getOutputStream();
		out.write(resXml.getBytes());
		out.flush();
		out.close();
	}

	/**
	 * 二维码消核
	 * 
	 * @author HEMING
	 * @email 910000889@qq.com
	 * @date 2018年7月7日
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/verify/{keys}")
	public @ResponseBody AjaxResult verify(@PathVariable("keys") String id) {
		LogUtil.debug("消核请求：{}", id);
		return null;
	}

}